package network;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Random;

import tools.Format;
import tools.Utils;

/*
 * To change this template, choose Tools | Templates and open the template in
 * the editor.
 */
/**
 *
 * @author Daisuke
 */
class Sender {

    private OutputStream out;
    public Sender(OutputStream out){
        
        this.out = out;
        
    }
    public  void sendCancel() throws IOException {

        out.write(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(13).order(ByteOrder.BIG_ENDIAN).array());
        out.write(8);
        out.write(ByteBuffer.allocate(4).putInt(0).order(ByteOrder.LITTLE_ENDIAN).array());
        out.write(ByteBuffer.allocate(4).putInt(0).order(ByteOrder.LITTLE_ENDIAN).array());
        out.write(ByteBuffer.allocate(4).putInt(42).order(ByteOrder.LITTLE_ENDIAN).array());

    }

    //<len=0005><id=4><piece index>
    public  void sendHave(int value) throws IOException {

        byte[] payload = Format.intToByteArray(value);
        MessageFactory message = new MessageFactory(4, payload);

        out.write(message.generate());
    }

    //<len=0001+X><id=5><bitfield>
    public  void sendBitfield(int nb_piece) throws IOException {


        byte[] bitfield = new byte[(nb_piece / 8) + 1];
        for (int i = 0; i <= nb_piece; i++) {
            setBit(bitfield, i, 0);
        }
        
        MessageFactory message = new MessageFactory(5, bitfield);
        out.write(message.generate());

    }
    


    //<len=0013><id=6><index><begin><length>
    public  void sendRequest(int index,int begin, int length) throws IOException {

        
        byte[] payload = Utils.concat(Format.intToByteArray(index), Utils.concat(Format.intToByteArray(begin),Format.intToByteArray(length)));
        MessageFactory message = new MessageFactory(6, payload);

        out.write(message.generate());


    }

    //<len=0009+X><id=7><index><begin><block>
    public  void sendPiece() throws IOException {

        System.out.println("Je n'enverrais pas de pièce tant que je n'aurais pas été reliée à une fonction getPiece");
    }

    public  void sendInterested() throws IOException {

        //ByteBuffer len = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(1).order(ByteOrder.BIG_ENDIAN);
        MessageFactory message = new MessageFactory(2);
        out.write(message.generate());
    }

    public  void sendNotInterested() throws IOException {

        MessageFactory message = new MessageFactory(3);
        out.write(message.generate());
    }

    public  void sendUnchoke() throws IOException {

        MessageFactory message = new MessageFactory(1);
        out.write(message.generate());
    }

    public  void sendChoke() throws IOException {

        MessageFactory message = new MessageFactory(0);
        out.write(message.generate());
    }

    public  void sendKeepALive() throws IOException {

        out.write(0);
    }

    public  byte[] generatePeerId() throws UnsupportedEncodingException {

        byte[] peer_id = new byte[20];
        byte[] version = "-DS1337-".getBytes();
        Random random = new Random();

//        for (int i = 0; i < version.length; i++) {
//            peer_id[i] = version[i];
//        }

        System.arraycopy(version, 0, peer_id, 0, version.length);

        String chars = "0123456789";

        for (int i = version.length; i < 20; i++) {
            char carac = chars.charAt(random.nextInt(10));
            peer_id[i] = ((byte) ((int) carac));
        }
        return peer_id;

    }

    public  void setBit(byte[] data, int pos, int val) {
        int posByte = pos / 8;
        int posBit = pos % 8;
        byte oldByte = data[posByte];
        oldByte = (byte) (((0xFF7F >> posBit) & oldByte) & 0x00FF);
        byte newByte = (byte) ((val << (8 - (posBit + 1))) | oldByte);
        data[posByte] = newByte;
    }

    public  int getBit(byte[] data, int pos) {
        int posByte = pos / 8;
        int posBit = pos % 8;
        byte valByte = data[posByte];
        int valInt = valByte >> (8 - (posBit + 1)) & 0x0001;
        return valInt;
    }
}
